home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / Mesa-3.0 / SRC / FOG.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-27  |  11.0 KB  |  372 lines

  1. /* $Id: fog.c,v 3.2 1998/03/27 03:37:40 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: fog.c,v $
  26.  * Revision 3.2  1998/03/27 03:37:40  brianp
  27.  * fixed G++ warnings
  28.  *
  29.  * Revision 3.1  1998/02/08 20:18:41  brianp
  30.  * removed unneeded headers
  31.  *
  32.  * Revision 3.0  1998/01/31 20:52:49  brianp
  33.  * initial rev
  34.  *
  35.  */
  36.  
  37.  
  38. #ifdef PC_HEADER
  39. #include "all.h"
  40. #else
  41. #include <math.h>
  42. #include <stdlib.h>
  43. #include "context.h"
  44. #include "fog.h"
  45. #include "macros.h"
  46. #include "types.h"
  47. #endif
  48.  
  49.  
  50.  
  51. void gl_Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *params )
  52. {
  53.    GLenum m;
  54.  
  55.    switch (pname) {
  56.       case GL_FOG_MODE:
  57.          m = (GLenum) (GLint) *params;
  58.      if (m==GL_LINEAR || m==GL_EXP || m==GL_EXP2) {
  59.         ctx->Fog.Mode = m;
  60.      }
  61.      else {
  62.         gl_error( ctx, GL_INVALID_ENUM, "glFog" );
  63.      }
  64.      break;
  65.       case GL_FOG_DENSITY:
  66.      if (*params<0.0) {
  67.         gl_error( ctx, GL_INVALID_VALUE, "glFog" );
  68.      }
  69.      else {
  70.         ctx->Fog.Density = *params;
  71.      }
  72.      break;
  73.       case GL_FOG_START:
  74. #if 0
  75.          /* Prior to OpenGL 1.1, this was an error */
  76.          if (*params<0.0F) {
  77.             gl_error( ctx, GL_INVALID_VALUE, "glFog(GL_FOG_START)" );
  78.             return;
  79.          }
  80. #endif
  81.      ctx->Fog.Start = *params;
  82.      break;
  83.       case GL_FOG_END:
  84. #if 0
  85.          /* Prior to OpenGL 1.1, this was an error */
  86.          if (*params<0.0F) {
  87.             gl_error( ctx, GL_INVALID_VALUE, "glFog(GL_FOG_END)" );
  88.             return;
  89.          }
  90. #endif
  91.      ctx->Fog.End = *params;
  92.      break;
  93.       case GL_FOG_INDEX:
  94.      ctx->Fog.Index = *params;
  95.      break;
  96.       case GL_FOG_COLOR:
  97.      ctx->Fog.Color[0] = params[0];
  98.      ctx->Fog.Color[1] = params[1];
  99.      ctx->Fog.Color[2] = params[2];
  100.      ctx->Fog.Color[3] = params[3];
  101.          break;
  102.       default:
  103.          gl_error( ctx, GL_INVALID_ENUM, "glFog" );
  104.    }
  105. }
  106.  
  107.  
  108.  
  109.  
  110. /*
  111.  * Compute the fogged color for an array of vertices.
  112.  * Input:  n - number of vertices
  113.  *         v - array of vertices
  114.  *         color - the original vertex colors
  115.  * Output:  color - the fogged colors
  116.  */
  117. void gl_fog_rgba_vertices( const GLcontext *ctx,
  118.                            GLuint n, GLfloat v[][4], GLubyte color[][4] )
  119. {
  120.    GLuint i;
  121.    GLfloat d;
  122.    GLfloat rFog = ctx->Fog.Color[0] * 255.0F;
  123.    GLfloat gFog = ctx->Fog.Color[1] * 255.0F;
  124.    GLfloat bFog = ctx->Fog.Color[2] * 255.0F;
  125.    GLfloat end = ctx->Fog.End;
  126.  
  127.    switch (ctx->Fog.Mode) {
  128.       case GL_LINEAR:
  129.          d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
  130.          for (i=0;i<n;i++) {
  131.             GLfloat f = (end - ABSF(v[i][2])) * d;
  132.             f = CLAMP( f, 0.0F, 1.0F );
  133.             color[i][0] = (GLint) (f * color[i][0] + (1.0F-f) * rFog);
  134.             color[i][1] = (GLint) (f * color[i][1] + (1.0F-f) * gFog);
  135.             color[i][2] = (GLint) (f * color[i][2] + (1.0F-f) * bFog);
  136.          }
  137.      break;
  138.       case GL_EXP:
  139.          d = -ctx->Fog.Density;
  140.          for (i=0;i<n;i++) {
  141.             GLfloat f = exp( d * ABSF(v[i][2]) );
  142.             f = CLAMP( f, 0.0F, 1.0F );
  143.             color[i][0] = (GLint) (f * color[i][0] + (1.0F-f) * rFog);
  144.             color[i][1] = (GLint) (f * color[i][1] + (1.0F-f) * gFog);
  145.             color[i][2] = (GLint) (f * color[i][2] + (1.0F-f) * bFog);
  146.          }
  147.      break;
  148.       case GL_EXP2:
  149.          d = -(ctx->Fog.Density*ctx->Fog.Density);
  150.          for (i=0;i<n;i++) {
  151.             GLfloat z = ABSF(v[i][2]);
  152.             GLfloat f = exp( d * z*z );
  153.             f = CLAMP( f, 0.0F, 1.0F );
  154.             color[i][0] = (GLint) (f * color[i][0] + (1.0F-f) * rFog);
  155.             color[i][1] = (GLint) (f * color[i][1] + (1.0F-f) * gFog);
  156.             color[i][2] = (GLint) (f * color[i][2] + (1.0F-f) * bFog);
  157.          }
  158.      break;
  159.       default:
  160.          gl_problem(ctx, "Bad fog mode in gl_fog_rgba_vertices");
  161.          return;
  162.    }
  163. }
  164.  
  165.  
  166.  
  167. /*
  168.  * Compute the fogged color indexes for an array of vertices.
  169.  * Input:  n - number of vertices
  170.  *         v - array of vertices
  171.  * In/Out: indx - array of vertex color indexes
  172.  */
  173. void gl_fog_ci_vertices( const GLcontext *ctx,
  174.                          GLuint n, GLfloat v[][4], GLuint indx[] )
  175. {
  176.    /* NOTE: the extensive use of casts generates better/faster code for MIPS */
  177.    switch (ctx->Fog.Mode) {
  178.       case GL_LINEAR:
  179.          {
  180.             GLfloat d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
  181.             GLfloat fogindex = ctx->Fog.Index;
  182.             GLfloat fogend = ctx->Fog.End;
  183.             GLuint i;
  184.             for (i=0;i<n;i++) {
  185.                GLfloat f = (fogend - ABSF(v[i][2])) * d;
  186.                f = CLAMP( f, 0.0F, 1.0F );
  187.                indx[i] = (GLint)
  188.                          ((GLfloat) (GLint) indx[i] + (1.0F-f) * fogindex);
  189.             }
  190.          }
  191.      break;
  192.       case GL_EXP:
  193.          {
  194.             GLfloat d = -ctx->Fog.Density;
  195.             GLfloat fogindex = ctx->Fog.Index;
  196.             GLuint i;
  197.             for (i=0;i<n;i++) {
  198.                GLfloat f = exp( d * ABSF(v[i][2]) );
  199.                f = CLAMP( f, 0.0F, 1.0F );
  200.                indx[i] = (GLint)
  201.                          ((GLfloat) (GLint) indx[i] + (1.0F-f) * fogindex);
  202.             }
  203.          }
  204.      break;
  205.       case GL_EXP2:
  206.          {
  207.             GLfloat d = -(ctx->Fog.Density*ctx->Fog.Density);
  208.             GLfloat fogindex = ctx->Fog.Index;
  209.             GLuint i;
  210.             for (i=0;i<n;i++) {
  211.                GLfloat z = ABSF(v[i][2]);
  212.                GLfloat f = exp( -d * z*z );
  213.                f = CLAMP( f, 0.0F, 1.0F );
  214.                indx[i] = (GLint)
  215.                          ((GLfloat) (GLint) indx[i] + (1.0F-f) * fogindex);
  216.             }
  217.          }
  218.      break;
  219.       default:
  220.          gl_problem(ctx, "Bad fog mode in gl_fog_ci_vertices");
  221.          return;
  222.    }
  223. }
  224.  
  225.  
  226.  
  227.  
  228. /*
  229.  * Apply fog to an array of RGBA pixels.
  230.  * Input:  n - number of pixels
  231.  *         z - array of integer depth values
  232.  *         red, green, blue, alpha - pixel colors
  233.  * Output:  red, green, blue, alpha - fogged pixel colors
  234.  */
  235. void gl_fog_rgba_pixels( const GLcontext *ctx,
  236.                          GLuint n, const GLdepth z[], GLubyte rgba[][4] )
  237. {
  238.    GLfloat c = ctx->ProjectionMatrix[10];
  239.    GLfloat d = ctx->ProjectionMatrix[14];
  240.    GLuint i;
  241.  
  242.    GLfloat rFog = ctx->Fog.Color[0] * 255.0F;
  243.    GLfloat gFog = ctx->Fog.Color[1] * 255.0F;
  244.    GLfloat bFog = ctx->Fog.Color[2] * 255.0F;
  245.  
  246.    GLfloat tz = ctx->Viewport.Tz;
  247.    GLfloat szInv = 1.0F / ctx->Viewport.Sz;
  248.  
  249.    switch (ctx->Fog.Mode) {
  250.       case GL_LINEAR:
  251.          {
  252.             GLfloat fogEnd = ctx->Fog.End;
  253.             GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
  254.             for (i=0;i<n;i++) {
  255.                GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  256.                GLfloat eyez = -d / (c+ndcz);
  257.                GLfloat f, g;
  258.                if (eyez < 0.0)  eyez = -eyez;
  259.                f = (fogEnd - eyez) * fogScale;
  260.                f = CLAMP( f, 0.0F, 1.0F );
  261.                g = 1.0F - f;
  262.                rgba[i][RCOMP] = (GLint) (f * rgba[i][RCOMP] + g * rFog);
  263.                rgba[i][GCOMP] = (GLint) (f * rgba[i][GCOMP] + g * gFog);
  264.                rgba[i][BCOMP] = (GLint) (f * rgba[i][BCOMP] + g * bFog);
  265.             }
  266.          }
  267.      break;
  268.       case GL_EXP:
  269.      for (i=0;i<n;i++) {
  270.         GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  271.         GLfloat eyez = -d / (c+ndcz);
  272.             GLfloat f, g;
  273.         if (eyez < 0.0)  eyez = -eyez;
  274.         f = exp( -ctx->Fog.Density * eyez );
  275.         f = CLAMP( f, 0.0F, 1.0F );
  276.             g = 1.0F - f;
  277.             rgba[i][RCOMP] = (GLint) (f * rgba[i][RCOMP] + g * rFog);
  278.             rgba[i][GCOMP] = (GLint) (f * rgba[i][GCOMP] + g * gFog);
  279.             rgba[i][BCOMP] = (GLint) (f * rgba[i][BCOMP] + g * bFog);
  280.      }
  281.      break;
  282.       case GL_EXP2:
  283.          {
  284.             GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
  285.             for (i=0;i<n;i++) {
  286.                GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  287.                GLfloat eyez = -d / (c+ndcz);
  288.                GLfloat f, g;
  289.                if (eyez < 0.0)  eyez = -eyez;
  290.                f = exp( negDensitySquared * eyez*eyez );
  291.                f = CLAMP( f, 0.0F, 1.0F );
  292.                g = 1.0F - f;
  293.                rgba[i][RCOMP] = (GLint) (f * rgba[i][RCOMP] + g * rFog);
  294.                rgba[i][GCOMP] = (GLint) (f * rgba[i][GCOMP] + g * gFog);
  295.                rgba[i][BCOMP] = (GLint) (f * rgba[i][BCOMP] + g * bFog);
  296.             }
  297.          }
  298.      break;
  299.       default:
  300.          gl_problem(ctx, "Bad fog mode in gl_fog_rgba_pixels");
  301.          return;
  302.    }
  303. }
  304.  
  305.  
  306.  
  307.  
  308. /*
  309.  * Apply fog to an array of color index pixels.
  310.  * Input:  n - number of pixels
  311.  *         z - array of integer depth values
  312.  *         index - pixel color indexes
  313.  * Output:  index - fogged pixel color indexes
  314.  */
  315. void gl_fog_ci_pixels( const GLcontext *ctx,
  316.                        GLuint n, const GLdepth z[], GLuint index[] )
  317. {
  318.    GLfloat c = ctx->ProjectionMatrix[10];
  319.    GLfloat d = ctx->ProjectionMatrix[14];
  320.    GLuint i;
  321.  
  322.    GLfloat tz = ctx->Viewport.Tz;
  323.    GLfloat szInv = 1.0F / ctx->Viewport.Sz;
  324.  
  325.    switch (ctx->Fog.Mode) {
  326.       case GL_LINEAR:
  327.          {
  328.             GLfloat fogEnd = ctx->Fog.End;
  329.             GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
  330.             for (i=0;i<n;i++) {
  331.                GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  332.                GLfloat eyez = -d / (c+ndcz);
  333.                GLfloat f;
  334.                if (eyez < 0.0)  eyez = -eyez;
  335.                f = (fogEnd - eyez) * fogScale;
  336.                f = CLAMP( f, 0.0F, 1.0F );
  337.                index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
  338.             }
  339.      }
  340.      break;
  341.       case GL_EXP:
  342.          for (i=0;i<n;i++) {
  343.         GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  344.         GLfloat eyez = -d / (c+ndcz);
  345.             GLfloat f;
  346.         if (eyez < 0.0)  eyez = -eyez;
  347.         f = exp( -ctx->Fog.Density * eyez );
  348.         f = CLAMP( f, 0.0F, 1.0F );
  349.         index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
  350.      }
  351.      break;
  352.       case GL_EXP2:
  353.          {
  354.             GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
  355.             for (i=0;i<n;i++) {
  356.                GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
  357.                GLfloat eyez = -d / (c+ndcz);
  358.                GLfloat f;
  359.                if (eyez < 0.0)  eyez = -eyez;
  360.                f = exp( negDensitySquared * eyez*eyez );
  361.                f = CLAMP( f, 0.0F, 1.0F );
  362.                index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
  363.             }
  364.      }
  365.      break;
  366.       default:
  367.          gl_problem(ctx, "Bad fog mode in gl_fog_ci_pixels");
  368.          return;
  369.    }
  370. }
  371.  
  372.